// 
// descriptor_tables.h - Defines the interface for initialising the GDT and IDT.
//                       Also defines needed structures.

#ifndef _DESC_TABLE_H_
#define _DESC_TABLE_H_

#include "common.h"

// Initialisation function is publicly accessible.
void init_descriptor_tables();

#define NULL_SEGMENT		0x00
#define	KERNEL_CODE_SEG		0x01
#define KERNEL_DATA_SEG		0x02
#define USER_CODE_SEG		0x03
#define USER_DATA_SEG		0x04

#define RING0		(0x00)
#define RING3		(0x60)
#define CODE_SEG	0x9A
#define DATA_SEG 	0x92

// This structure contains the value of one GDT entry.
// We use the attribute 'packed' to tell GCC not to change
// any of the alignment in the structure.
struct gdt_entry
{
    u16int limit_0_15;           // The lower 16 bits of the limit.
    u16int base_0_15;            // The lower 16 bits of the base.
    u8int  base_16_23;         // The next 8 bits of the base.
    // Access Byte format
    u32int type		: 4;  // (code/data, direction bit, rw, ac)
    u32int dt		: 1;  // descriptor type
    u32int dpl		: 2;  // Privilege level
    u32int pr		: 1;  // Is segment present? (1 = Yes)
    u32int limit_16_19  : 4;
    // Granurality byte format
    u32int av		: 1; 
    u32int unused	: 1;
    u32int size_bit	: 1;
    u32int gran         : 1;
    u8int base_24_31;
} __attribute__((packed));

// This struct describes a GDT pointer. It points to the start of
// our array of GDT entries, and is in the format required by the
// lgdt instruction.
struct gdt_ptr_struct
{
    u16int limit;               // The upper 16 bits of all selector limits.
    u32int base;                // The address of the first gdt_entry_t struct.
} __attribute__((packed));

typedef struct gdt_ptr_struct gdt_ptr_t;

// A struct describing an interrupt gate.
struct idt_entry_struct
{
    u16int base_lo;             // The lower 16 bits of the address to jump to when this interrupt fires.
    u16int sel;                 // Kernel segment selector.
    u8int  always0;             // This must always be zero.
    u8int  flags;               // More flags. See documentation.
    u16int base_hi;             // The upper 16 bits of the address to jump to.
} __attribute__((packed));

typedef struct idt_entry_struct idt_entry_t;

// A struct describing a pointer to an array of interrupt handlers.
// This is in a format suitable for giving to 'lidt'.
struct idt_ptr_struct
{
    u16int limit;
    u32int base;                // The address of the first element in our idt_entry_t array.
} __attribute__((packed));

typedef struct idt_ptr_struct idt_ptr_t;

// These extern directives let us access the addresses of our ASM ISR handlers.
extern void isr0 ();
extern void isr1 ();
extern void isr2 ();
extern void isr3 ();
extern void isr4 ();
extern void isr5 ();
extern void isr6 ();
extern void isr7 ();
extern void isr8 ();
extern void isr9 ();
extern void isr10();
extern void isr11();
extern void isr12();
extern void isr13();
extern void isr14();
extern void isr15();
extern void isr16();
extern void isr17();
extern void isr18();
extern void isr19();
extern void isr20();
extern void isr21();
extern void isr22();
extern void isr23();
extern void isr24();
extern void isr25();
extern void isr26();
extern void isr27();
extern void isr28();
extern void isr29();
extern void isr30();
extern void isr31();
extern void irq0 ();
extern void irq1 ();
extern void irq2 ();
extern void irq3 ();
extern void irq4 ();
extern void irq5 ();
extern void irq6 ();
extern void irq7 ();
extern void irq8 ();
extern void irq9 ();
extern void irq10();
extern void irq11();
extern void irq12();
extern void irq13();
extern void irq14();
extern void irq15();

#endif


